package com.baofu.paycore.web.controller;

import com.baofu.account.service.facade.enums.CurrencyEnum;
import com.baofu.paycore.common.enums.CardTypeEnum;
import com.baofu.paycore.service.facade.TransferServiceFacade;
import com.baofu.paycore.service.facade.enums.ServiceCodeEnum;
import com.baofu.paycore.service.PayService;
import com.baofu.paycore.service.RechargeService;
import com.baofu.paycore.service.facade.WithdrawServiceFacade;
import com.baofu.paycore.service.facade.enums.PayToolSubTypeEnum;
import com.baofu.paycore.service.facade.enums.PayToolTypeEnum;
import com.baofu.paycore.service.facade.model.FundBaseDTO;
import com.baofu.paycore.service.facade.model.WebPayResDTO;
import com.baofu.paycore.service.facade.model.pay.FundDetailInfoDTO;
import com.baofu.paycore.service.facade.model.pay.PayDTO;
import com.baofu.paycore.service.facade.model.recharge.RechargeDTO;
import com.baofu.paycore.service.facade.model.recharge.RechargeResDTO;
import com.baofu.paycore.service.facade.model.transfer.TransferDTO;
import com.baofu.paycore.service.facade.model.transfer.TransferFundDTO;
import com.baofu.paycore.service.facade.model.transfer.TransferResDTO;
import com.baofu.paycore.service.facade.model.withdraw.WithDrawFundDTO;
import com.baofu.paycore.service.facade.model.withdraw.WithdrawDTO;
import com.baofu.paycore.service.facade.model.withdraw.WithdrawResDTO;
import com.baofu.paycore.web.controller.model.WebPayVO;
import com.google.common.collect.Lists;
import com.system.commons.result.Result;
import com.system.commons.sequence.redis.SequenceFacade;
import com.system.commons.utils.BeanCopyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 支付控制器
 *
 * <p>
 *      1.web支付测试
 * </p>
 * User: xin deng  Date: 16/5/18 ProjectName: paycore Version: 1.0
 */
@Slf4j
@Controller
@RequestMapping
public class PayController {

    @Autowired
    private PayService payService;

    @Autowired
    private RechargeService rechargeService;

    @Autowired
    private TransferServiceFacade transferServiceFacade;

    /**
     * 提现服务
     */
    @Autowired(required = false)
    private WithdrawServiceFacade withdrawService;

    @Autowired
    private SequenceFacade sequenceFacade;

    @RequestMapping("webPay")
    public String pay(){
        return "webPay";
    }

//    @RequestMapping("/pay/webPay")
    public String webPay(WebPayVO webPayVO, Model model){
        try {
            log.info("界面入参:{}", webPayVO);

            PayDTO payDTO = BeanCopyUtil.objConvert(webPayVO, PayDTO.class);
            payDTO.setRequestDate(new Date());
            List<FundDetailInfoDTO> payers = new ArrayList<>();
            if(StringUtils.isNotEmpty(webPayVO.getPayerFundDetail01().getPayToolAmount())){
                FundDetailInfoDTO fundDetailInfoDTO01 =
                        BeanCopyUtil.objConvert(webPayVO.getPayerFundDetail01(),FundDetailInfoDTO.class);
                fundDetailInfoDTO01.setPayToolAmount(Long.valueOf(webPayVO.getPayerFundDetail01().getPayToolAmount()));
                payers.add(fundDetailInfoDTO01);
            }
            if(StringUtils.isNotEmpty(webPayVO.getPayerFundDetail02().getPayToolAmount())){
                FundDetailInfoDTO fundDetailInfoDTO02 =
                        BeanCopyUtil.objConvert(webPayVO.getPayerFundDetail02(),FundDetailInfoDTO.class);
                fundDetailInfoDTO02.setPayToolAmount(Long.valueOf(webPayVO.getPayerFundDetail02().getPayToolAmount()));
                payers.add(fundDetailInfoDTO02);
            }
            FundDetailInfoDTO payee = BeanCopyUtil.objConvert(webPayVO.getPayeeFundDetail(), FundDetailInfoDTO.class);
            payee.setPayToolAmount(Long.valueOf(webPayVO.getPayeeFundDetail().getPayToolAmount()));
            payDTO.setPayeeFundDetail(payee);
            payDTO.setPayerFundDetails(payers);
            payDTO.setRelationNo(payDTO.getRequestOrderNo());
            log.info("web支付 参数:{}", payDTO);

            Result<WebPayResDTO> result = payService.webPay(payDTO, UUID.randomUUID().toString());
            log.error("支付结果:{}",result);
            if (!result.isSuccess()){
                return null;
            }

            model.addAttribute("url", result.getResult().getOutPayUrl());
            model.addAttribute("params", result.getResult().getParams());
        } catch (Exception e){
            log.error("web 支付异常:{}",e);
            return null;
        }
        return "redirect";
    }

    /**
     * 组装请求参数
     *
     * @return      支付订单
     */
    public PayDTO before() {
        PayDTO payDTO = new PayDTO();
        payDTO.setRequestSystem("WG");
        payDTO.setRequestChannel("WEB");
        payDTO.setRequestDate(new Date());
        payDTO.setRequestBizNo(String.valueOf(System.currentTimeMillis()) + "abcdefg");
        payDTO.setBizType("充值");
        payDTO.setSubBizType("快捷支付");
        payDTO.setServiceCode("PAY");
        payDTO.setAmt(3l);
        payDTO.setRequestOrderNo(System.currentTimeMillis() + "");
        payDTO.setCcy(CurrencyEnum.CNY.getCode());
        payDTO.setEventNo("40000001");
        payDTO.setPayerAccNo("97100000000423156");
        payDTO.setPayeeNo("3177000000000043");
        payDTO.setPayerNo("3177000000000044");
        List<FundDetailInfoDTO> consumeFundDTOs = Lists.newArrayList();
        initBankFund(consumeFundDTOs);
        payDTO.setPayerFundDetails(consumeFundDTOs);

        FundDetailInfoDTO consumeFundDTO = new FundDetailInfoDTO();
        consumeFundDTO.setAccountNo("87100000000141156");
        consumeFundDTO.setCcy(CurrencyEnum.CNY.getCode());
        consumeFundDTO.setPayToolAmount(3l);
        consumeFundDTO.setPayToolType(PayToolTypeEnum.ACCOUNT.getCode());
        consumeFundDTO.setPayToolSubType(PayToolSubTypeEnum.ACCOUNT.getSubPayToolCode());
        consumeFundDTO.setDescription("测试");
        payDTO.setPayeeFundDetail(consumeFundDTO);

        return payDTO;
    }

    /**
     * 卡付款
     */
    private void initBankFund(List<FundDetailInfoDTO> consumeFundDTOs){
        FundDetailInfoDTO consumeFundDTO = new FundDetailInfoDTO();
        consumeFundDTO.setAccountNo("71031780000000002163156");
        consumeFundDTO.setCcy(CurrencyEnum.CNY.getCode());
        consumeFundDTO.setPayToolAmount(3l);
        consumeFundDTO.setPayToolType(PayToolTypeEnum.BANK_CARD.getCode());
        consumeFundDTO.setCardType("D");
        consumeFundDTO.setBankCode("ICBC_D");
        consumeFundDTO.setPayToolSubType("Account");
        consumeFundDTO.setDescription("测试");
        consumeFundDTO.setAgreeRelId("1");
        consumeFundDTO.setAgreementNo("1231231312");
        consumeFundDTOs.add(consumeFundDTO);
    }

//    @RequestMapping("withdraw")
    public String withdraw(){
        WithdrawDTO withdrawDTO = new WithdrawDTO();
        withdrawDTO.setRequestSystem("WEB");
        withdrawDTO.setServiceCode(ServiceCodeEnum.WITHDRAW.getCode());
        withdrawDTO.setRequestOrderNo(sequenceFacade.getUniqueSeq());
        withdrawDTO.setRequestBizNo(sequenceFacade.getUniqueSeq());
        withdrawDTO.setRequestDate(new Date());
        withdrawDTO.setCcy("CNY");
        withdrawDTO.setAmt(150l);
        withdrawDTO.setBizType("WITHDRAW");
        withdrawDTO.setSubBizType("BANK_CARD");
        withdrawDTO.setMerchantNo("88288888");
        withdrawDTO.setDescription("测试支付提现");
        withdrawDTO.setOperator("ceshi");
        withdrawDTO.setRequestChannel("WEB");

        withdrawDTO.setContractNo("3177000000014072");
        withdrawDTO.setAccountNo("97100000000423156");
//        withdrawDTO.setBankCode("SPDB");
        withdrawDTO.setCardType(CardTypeEnum.CREDIT_CARD.getCode());

        WithDrawFundDTO withDrawFundDTO = new WithDrawFundDTO();
        withDrawFundDTO.setBizChargeAmount(2l);
        withDrawFundDTO.setAgreeRelId("15");
        withDrawFundDTO.setAgreementNo("14");
        withDrawFundDTO.setCcy("CNY");
        withDrawFundDTO.setAmt(150l);
        withDrawFundDTO.setDescription("测试");
        withdrawDTO.setWithDrawFundDTO(withDrawFundDTO);

        log.info("提现开始 参数:{}", withdrawDTO);
        Result<WithdrawResDTO> result = withdrawService.withdraw(withdrawDTO, UUID.randomUUID()+"");
        log.info("提现流程结束:{}", result);

        return null;
    }

//    @RequestMapping("recharge")
    public String recharge(){
        RechargeDTO rechargeDTO = new RechargeDTO();
        rechargeDTO.setRequestSystem("TRADECENTER");
        rechargeDTO.setRequestChannel("WEB");
        rechargeDTO.setRequestDate(new Date());
        rechargeDTO.setRequestBizNo(String.valueOf(System.currentTimeMillis()) + "abcdefg");
        rechargeDTO.setRequestOrderNo(String.valueOf(System.currentTimeMillis())+"aaaa");
        rechargeDTO.setCcy("CNY");
        rechargeDTO.setAccountNo("97100000000061156");
        rechargeDTO.setServiceCode("RECHARGE");
        rechargeDTO.setBizType("RECHARGE");
        rechargeDTO.setSubBizType("FEE");
        rechargeDTO.setAmt(200l);
//        rechargeDTO.setSourceAmt("31");
        rechargeDTO.setContractNo("3177000000000062");
//        rechargeDTO.setContractNo("12312312");
//        rechargeDTO.setEventNo("30000001");
        rechargeDTO.setOperator("system");
        FundBaseDTO rechargeFundDTO = new FundBaseDTO();
        rechargeFundDTO.setPayToolType(PayToolTypeEnum.BANK_CARD.getCode());
        rechargeFundDTO.setPayToolSubType(PayToolSubTypeEnum.QUICK_PAY_C.getSubPayToolCode());
        rechargeFundDTO.setBizFeeAccount("97100000000061156");
        rechargeFundDTO.setBizChargeAmount(1l);
        rechargeFundDTO.setCcy("CNY");
        rechargeFundDTO.setAmt(200l);
        rechargeFundDTO.setBankCode("ICBC_D");
        rechargeFundDTO.setCardType("D");
        rechargeFundDTO.setAgreeRelId("2");
        rechargeFundDTO.setAgreementNo("");
//        rechargeFundDTO.setOpFlag("00");


        rechargeDTO.setFundBaseDTO(rechargeFundDTO);

        log.info("充值开始 参数:{}", rechargeDTO);
        Result<RechargeResDTO> result = rechargeService.recharge(rechargeDTO,UUID.randomUUID().toString());
        log.info("充值结束 结果:{}", result);

        return null;
    }

    @RequestMapping("transfer")
    @ResponseBody
    public String transfer(String eventNo,String inAccount,String outAccount,String bizType,String subBizType){

        TransferDTO transferDTO =  build(eventNo,inAccount,outAccount);
        log.info("转账开始 参数:{},{},{},{},{},{}", eventNo,inAccount,outAccount,bizType,subBizType,transferDTO.getRequestOrderNo());
        Result<TransferResDTO>  result = transferServiceFacade.transfer(transferDTO,UUID.randomUUID().toString());
        log.info("转账结束 结果:{}", result);

        return result.isSuccess() ? result.getResult().getStatus() : result.getErrorCode()+result.getErrorMsg();
    }


    public static TransferDTO build(String eventNo,String inAccount,String outAccount){
        SimpleDateFormat formatter = new SimpleDateFormat("MMddHHmmssSSS");
        String formatStr =formatter.format(new Date());
        long a = (long) (Math.random()*100000000);
        long b = (long)(Math.random()*100000000);
        TransferDTO transferDTO = new TransferDTO();
        transferDTO.setTransferInDTO(inAccount(inAccount));
        transferDTO.setTransferOutDTO(outAccount(outAccount));
        transferDTO.setServiceCode("TRANSFER");
        transferDTO.setRequestSystem("WG");
        transferDTO.setRequestChannel("WEB");
        transferDTO.setRequestDate(new Date());
        transferDTO.setRelationNo(formatStr+a+b);
        transferDTO.setRequestBizNo(formatStr+a);
        transferDTO.setRequestOrderNo(formatStr+a+b);
        transferDTO.setBizType("TRANSFER");
        transferDTO.setSubBizType("FEE");
        transferDTO.setEventNo(eventNo);
        transferDTO.setAmt(3L);
        transferDTO.setCcy("CNY");
        transferDTO.setOperator("LZQ");
        return transferDTO;
    }


    /**
     * 转出方
     */
    private static TransferFundDTO outAccount(String outAccount){
        TransferFundDTO transferFundDTO = new TransferFundDTO();
        transferFundDTO.setAccountNo(outAccount);
        transferFundDTO.setContractNo("def");
        return transferFundDTO;
    }


    /**
     * 转入方
     */
    private static TransferFundDTO inAccount(String inAccount){
        TransferFundDTO transferFundDTO = new TransferFundDTO();
        transferFundDTO.setAccountNo(inAccount);
        transferFundDTO.setContractNo("abc");
        return transferFundDTO;
    }

}
